﻿#include "FITKAbaqusHDF5Reader.h"
#include "FITKAbaqusHDF5AdaptorCase.h"
#include "FITKAbaqusHDF5AdaptorJob.h"

#include "FITK_Kernel/FITKAppFramework/FITKMessage.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Kernel/FITKCore/FITKAbstractDataManager.hpp"
#include "FITK_Kernel/FITKCore/FITKDataRepo.h"
#include "FITK_Component/FITKAbaqusData/FITKDataCaseManager.h"
#include "FITK_Component/FITKAbaqusData/FITKDataCase.h"
#include "FITK_Component/FITKAbaqusData/FITKAbaqusData.h"
#include "FITK_Component/FITKAbaqusData/FITKJob.h"
#include "FITK_Component/FITKAbaqusData/FITKJobManager.h"
#include "H5Cpp.h"
#include <QDebug>

namespace IO
{
    FITKAbaqusHDF5Reader::FITKAbaqusHDF5Reader()
    {

    }

    FITKAbaqusHDF5Reader::~FITKAbaqusHDF5Reader()
    {

    }


    void FITKAbaqusHDF5Reader::run()
    {
        *_resultMark = false;
        auto abaqusData = dynamic_cast<AbaqusData::FITKAbaqusData*>(_data);
        if (!abaqusData || !_h5File) return;
        _caseManager = abaqusData->getDataCaseManager();
        //清空全部算例
        if (_caseManager) _caseManager->clearAllCase();
        _jobManager = abaqusData->getJobManager();
        if (_jobManager) _jobManager->clear();

        if (!_caseManager || !_jobManager) return;
        *_resultMark = true;
        *_resultMark &= readVersion();
        *_resultMark &= readDataCases();
        *_resultMark &= readJobs();
        //检查算例数量，保证至少有一个算例
        _caseManager->checkCaseNum();

    }

    bool FITKAbaqusHDF5Reader::readDataCases()
    {
        std::string name = "Cases";
        bool isR = true;
        // create cases group
        if (!_h5File->nameExists(name)) return false;
        H5::Group casesGroup = _h5File->openGroup(name);

        int count = casesGroup.getNumAttrs();
        for (int i = 0; i < count; i++)
        {
            QString indexName = QString::number(i);
            if (!casesGroup.attrExists(indexName.toStdString()))
            {
                consoleMessage(3, QString("Read Case Error, CaseIndex : %1").arg(indexName));
                return false;
            }

            auto casesAttribute = casesGroup.openAttribute(indexName.toStdString());
            //case name
            std::string caseName;
            H5::StrType datatype(H5::PredType::C_S1, H5T_VARIABLE);
            casesAttribute.read(datatype, caseName);
            if (!casesGroup.nameExists(caseName))
            {
                consoleMessage(3, QString("Read Case Error, CaseName : %1").arg(QString::fromStdString(caseName)));
                return false;
            }
            auto caseGroup = casesGroup.openGroup(caseName);

            AbaqusData::FITKDataCase* dataCase = new AbaqusData::FITKDataCase();
            _caseManager->appendDataObj(dataCase);

            FITKAbaqusHDF5AdaptorCase* adaptor = FITKIOADAPTORFACTORY->createT<FITKAbaqusHDF5AdaptorCase>("HDF5", dataCase);
            if (!adaptor) return false;
            adaptor->setH5GroupData(caseGroup);
            adaptor->setDataObject(dataCase);
            adaptor->setFileReader(this);
            bool R = adaptor->adaptR();
            if (!R)
            {
                consoleMessage(3, QString("Read Case Error, CaseName : %1").arg(QString::fromStdString(caseName)));
                //delete dataCase;
            }
            delete adaptor;
            isR &= R;
        }
        return isR;
    }

    bool FITKAbaqusHDF5Reader::readJobs()
    {
        bool isR = true;
        // read Jobs group
        H5::Group JobsGroup = _h5File->openGroup("Jobs");
        int jobCount = JobsGroup.getNumAttrs();
        for (int i = 0; i < jobCount; ++i)
        {
            QString indexName = QString::number(i);
            if (!JobsGroup.attrExists(indexName.toStdString())) continue;
            std::string jobName;
            H5::StrType datatype(H5::PredType::C_S1, H5T_VARIABLE);
            H5::Attribute att = JobsGroup.openAttribute(indexName.toStdString());
            att.read(datatype, jobName);
            auto JobGroup = JobsGroup.openGroup(jobName);
            AbaqusData::FITKJob* jobData = new AbaqusData::FITKJob();
            _jobManager->appendDataObj(jobData);
            auto adaptor = FITKIOADAPTORFACTORY->createT<FITKAbaqusHDF5AdaptorJob>("HDF5", "AbaqusData::FITKJob");
            if (adaptor == nullptr) return false;
            adaptor->setH5GroupData(JobGroup);
            adaptor->setDataObject(jobData);
            adaptor->setFileReader(this);
            bool r = adaptor->adaptR();
            if (!r)
            {
                consoleMessage(3, QString("Read Job Errors, JobName : %1").arg(QString::fromStdString(jobName)));
                delete jobData;
            }
            isR &= r;
            delete adaptor;
        }
        return isR;
    }

    bool FITKAbaqusHDF5Reader::readVersion()
    {
        //写出HDF5管理功能版本号
        std::string name = "Version";
        if (!_h5File->nameExists(name)) return false;
        H5::Group versionGroup = _h5File->openGroup(name);
        if (!versionGroup.attrExists(name)) return false;
        auto attrVersion = versionGroup.openAttribute(name);
        double version = -1;
        attrVersion.read(H5::PredType::NATIVE_DOUBLE, &version);
        consoleMessage(1, QString("HDF5 SoftWare Version : %1, HDF5 File Version : %2").arg(_version).arg(version));
        if (version > _version)
        {
            consoleMessage(2, "Read Error, File Version Mismatch.");
            return false;
        }
        return true;
    }

    void FITKAbaqusHDF5Reader::consoleMessage(int level, const QString & str)
    {
        qDebug() << str;
        //判断消息等级
        switch (level)
        {
        case 1:AppFrame::FITKMessageNormal(str); break;
        case 2: AppFrame::FITKMessageWarning(str); break;
        case 3:AppFrame::FITKMessageError(str); break;
        default: AppFrame::FITKMessageError(str); break;
        }
    }
}
